<template>
  <view class="qc-navigation-bar" :class="{ 'qc-bar-line': opacity > 0.85 && splitLine, 'qc-navbar-fixed': isFixed, 'qc-backdrop__filter': backdropFilter && dropDownOpacity > 0  }" :style="{ height: height + 'px', backgroundColor: `rgba(${background},${opacity})`, opacity: dropDownOpacity, zIndex: isFixed ? zIndex : 'auto' }">
    <view class="qc-status-bar" :style="{ height: statusBarHeight + 'px' }" v-if="isImmersive"></view>
    <view class="qc-navigation_bar-title" :style="{ opacity: transparent || opacity >= maxOpacity ? 1 : opacity, color: color, paddingTop: top - statusBarHeight + 'px' }" v-if="title && !isCustom">
      {{ title }}
    </view>
    <slot></slot>
  </view>
</template>

<script>
export default {
  name: 'qcNavigationBar',
  emits: ['init', 'change'],
  props: {
    title: {
      type: String,
      default: ''
    },
    color: {
      type: String,
      default: '#333'
    },
    backgroundColor: {
      type: String,
      default: '#fff'
    },
    splitLine: {
      type: Boolean,
      default: false
    },
    isOpacity: {
      type: Boolean,
      default: true
    },
    maxOpacity: {
      type: [Number, String],
      default: 1
    },
    transparent: {
      type: Boolean,
      default: false
    },
    scrollTop: {
      type: [Number, String],
      default: 0
    },
    scrollRatio: {
      type: [Number, String],
      default: 0.3
    },
    isCustom: {
      type: Boolean,
      default: false
    },
    isImmersive: {
      type: Boolean,
      default: true
    },
    isFixed: {
      type: Boolean,
      default: true
    },
    backdropFilter: {
      type: Boolean,
      default: false
    },
    dropDownHide: {
      type: Boolean,
      default: false
    },
    zIndex: {
      type: [Number, String],
      default: 996
    }
  },
  watch: {
    scrollTop(newValue, oldValue) {
      if (newValue === oldValue) return;
      if (this.isOpacity && !this.transparent) {
        this.opacityChange();
      }
    },
    backgroundColor(val) {
      if (val) {
        this.background = this.hexToRgb(val);
      }
    }
  },
  data() {
    return {
      width: 375,
      left: 375,
      height: 44,
      top: 0,
      scrollH: 1,
      opacity: 1,
      statusBarHeight: 0,
      background: '255,255,255',
      dropDownOpacity: 1
    };
  },
  created() {
    this.dropDownOpacity = this.backdropFilter ? 0 : this.dropDownOpacity;
    this.opacity = (this.isOpacity || this.transparent) ? 0 : Number(this.maxOpacity);
    this.background = this.hexToRgb(this.backgroundColor);
    let obj = wx.getMenuButtonBoundingClientRect();
    uni.getSystemInfo({
      success: res => {
        this.statusBarHeight = res.statusBarHeight;
        this.width = res.windowWidth;
        this.left = obj.left || res.windowWidth;
        if (this.isImmersive) {
          this.height = obj.top ? obj.top + obj.height + 8 : res.statusBarHeight + 44;
        }
        this.scrollH = res.windowWidth * Number(this.scrollRatio);
        this.top = obj.top ? obj.top + (obj.height - 32) / 2 : res.statusBarHeight + 6;
        this.$emit('init', {
          width: this.width,
          height: this.height,
          left: this.left,
          top: this.top,
          statusBarHeight: this.statusBarHeight,
          opacity: this.opacity,
          windowHeight: res.windowHeight
        });
      }
    });
  },
  methods: {
    clamp(val, min, max) {
      const n = Number(val);
      if (Number.isNaN(n)) return min;
      return Math.min(Math.max(n, min), max);
    },
    hexToRgb(hex) {
      let rgb = '255,255,255';
      if (hex && hex.indexOf('#') !== -1) {
        if (hex.length === 4) {
          let text = hex.substring(1, 4);
          hex = '#' + text + text;
        }
        let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        if (result) {
          rgb = `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}`;
        }
      }
      return rgb;
    },
    opacityChange() {
      if (this.dropDownHide) {
        if (Number(this.scrollTop) < 0) {
          const next = 1 - Math.abs(Number(this.scrollTop)) / 30;
          this.dropDownOpacity = this.clamp(next, 0, 1);
        } else {
          this.dropDownOpacity = 1;
        }
      }

      const scrollTopNum = Number(this.scrollTop);
      const scroll = scrollTopNum <= 1 ? 0 : scrollTopNum;
      const max = Number(this.maxOpacity) || 1;
      const denominator = Number(this.scrollH) || 1;
      const opacity = scroll / denominator;
      if ((this.opacity >= max && opacity >= max) || (this.opacity === 0 && opacity === 0)) {
        return;
      }
      const nextOpacity = opacity > max ? max : this.clamp(opacity, 0, max);
      if (nextOpacity === this.opacity) return;
      this.opacity = nextOpacity;
      if (this.backdropFilter) {
        this.dropDownOpacity = this.opacity >= max ? 1 : this.opacity;
      }
      this.$emit('change', {
        opacity: this.opacity
      });
    }
  }
};
</script>

<style scoped>
.qc-navigation-bar {
  width: 100%;
  transition: opacity 0.4s;
  will-change: opacity;
}

.qc-backdrop__filter {
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
}

.qc-navbar-fixed {
  position: fixed;
  left: 0;
  top: 0;
}

.qc-status-bar {
  width: 100%;
}

.qc-navigation_bar-title {
  width: 100%;
  font-size: 17px;
  line-height: 17px;
  font-weight: 500;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.qc-bar-line::after {
  content: '';
  position: absolute;
  border-bottom: 1rpx solid #eaeef1;
  -webkit-transform: scaleY(0.5);
  transform: scaleY(0.5);
  bottom: 0;
  right: 0;
  left: 0;
}
</style>
